home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 6 code / TCP / NewsWatcher / NW Source / Shared Code / Reusable Source / tescroll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-05  |  9.5 KB  |  348 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     tescroll.c
  4.  
  5.     This reusable module manages simple TextEdit fields with vertical 
  6.     scroll bars.
  7.     
  8.     Copyright © 1994-1995, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include "def.h"
  13. #include "tescroll.h"
  14. #include "teutil.h"
  15.  
  16.  
  17.  
  18.  
  19. /*----------------------------------------------------------------------------
  20.     TEScrollNumTELines 
  21.     
  22.     Get the number of lines in a TE field.
  23.             
  24.     Entry:    theTE = handle to TextEdit record.
  25.     
  26.     Exit:    function result = number of lines in field.
  27. ----------------------------------------------------------------------------*/
  28.  
  29. short TEScrollNumTELines (TEHandle theTE)
  30. {
  31.     short nLines;
  32.     Handle hText;
  33.     short teLength;
  34.  
  35.     nLines = (**theTE).nLines;
  36.     if (nLines == 0) {
  37.         nLines = 1;
  38.     } else {
  39.         hText = (**theTE).hText;
  40.         teLength = (**theTE).teLength;
  41.         if (*(*hText + teLength - 1) == CR) nLines++;
  42.     }
  43.     return nLines;
  44. }
  45.  
  46.  
  47.  
  48. /*----------------------------------------------------------------------------
  49.     TEScrollGetTELineNumber 
  50.     
  51.     Get the line number of a character position in a TextEdit field.
  52.             
  53.     Entry:    charPos = character position (0-based).
  54.             theTE = handle to TextEdit record.
  55.             
  56.     Exit:    function result = line number (0-based).
  57. ----------------------------------------------------------------------------*/
  58.  
  59. short TEScrollGetTELineNumber (short charPos, TEHandle theTE)
  60. {
  61.     short *lineStarts;
  62.     short nLines;
  63.     short i;
  64.     Handle hText;
  65.  
  66.     lineStarts = (**theTE).lineStarts;
  67.     nLines = (**theTE).nLines;
  68.     i = 0;
  69.     while (i <= nLines && *lineStarts <= charPos) {
  70.         i++;
  71.         lineStarts++;
  72.     }
  73.     if (i == 0) return 0;
  74.     i--;
  75.     if (*(lineStarts-1) != charPos) return i;
  76.     if (i == 0) return 0;
  77.     hText = (**theTE).hText;
  78.     return MyGetClikStuff(theTE) == 0 ? i-1 : i;
  79. }
  80.  
  81.  
  82.  
  83. /*----------------------------------------------------------------------------
  84.     TEScrollAdjustScrollMax 
  85.     
  86.     Adjust the scroll bar maximum value.
  87.             
  88.     Entry:    theTE = handle to TextEdit record.
  89.             vScroll = handle to scroll bar control.
  90. ----------------------------------------------------------------------------*/
  91.  
  92. void TEScrollAdjustScrollMax (TEHandle theTE, ControlHandle vScroll)
  93. {
  94.     Rect viewRect, destRect;
  95.     short max, viewHeight;
  96.     short nLines, bottom, height, lineHeight;
  97.     
  98.     lineHeight = (**theTE).lineHeight;
  99.     viewRect = (**theTE).viewRect;
  100.     destRect = (**theTE).destRect;
  101.     nLines = TEScrollNumTELines(theTE);
  102.     viewHeight = viewRect.bottom - viewRect.top;
  103.     bottom = destRect.top + nLines*lineHeight;
  104.     if (bottom < viewRect.bottom) bottom = viewRect.bottom;
  105.     height = bottom - destRect.top;
  106.     max = height - viewHeight;
  107.     if (max < 0) max = 0;
  108.     SetControlMaximum(vScroll, max/lineHeight);
  109. }
  110.  
  111.  
  112.  
  113. /*----------------------------------------------------------------------------
  114.     TEScrollScrollText 
  115.     
  116.     Scroll text.
  117.             
  118.     Entry:    theTE = handle to TextEdit record.
  119.             vScroll = handle to scroll bar control.
  120.             dv = number of lines to scroll.
  121.             
  122.     If the scroll bar's refCon is non-zero, the scroll bar max value is
  123.     adjusted after the scrolling operation. This is what you normally want.
  124.     The only exception is when scrolling in a TrackControl action procedure,
  125.     when you want to set the refCon to zero.
  126. ----------------------------------------------------------------------------*/
  127.  
  128. void TEScrollScrollText (TEHandle theTE, ControlHandle vScroll, short dv)
  129. {
  130.     short lineHeight;
  131.     
  132.     lineHeight = (**theTE).lineHeight;
  133.     TEScroll(0, dv * lineHeight, theTE);
  134.     if (GetControlReference(vScroll) != 0) TEScrollAdjustScrollMax(theTE, vScroll);
  135. }
  136.  
  137.  
  138.  
  139. /*----------------------------------------------------------------------------
  140.     TEScrollScrollRangeIntoView 
  141.     
  142.     Scroll a range of characters into view, if necessary.
  143.             
  144.     Entry:    theTE = handle to TextEdit record.
  145.             start = starting offset of range.
  146.             end = ending offset of range.
  147.             vScroll = handle to scroll bar control.
  148. ----------------------------------------------------------------------------*/
  149.  
  150. void TEScrollScrollRangeIntoView (TEHandle theTE, short start, short end, 
  151.     ControlHandle vScroll)
  152. {
  153.     short lineStart, lineEnd, top, lineHeight, vStart, vEnd;
  154.     short oldScrollVal, max, dv;
  155.     Rect viewRect;
  156.     Boolean tooBig;
  157.     short selStart, selEnd, savedClikStuff;
  158.  
  159.     TEScrollAdjustScrollMax(theTE, vScroll);
  160.     savedClikStuff = (**theTE).clikStuff;
  161.     selStart = (**theTE).selStart;
  162.     selEnd = (**theTE).selEnd;
  163.     if (start == end && selStart < selEnd) {
  164.         if (start == selEnd) {
  165.             (**theTE).clikStuff = 0;
  166.         } else if (end == selStart) {
  167.             (**theTE).clikStuff = 0xffff;
  168.         }
  169.         lineStart = TEScrollGetTELineNumber(start, theTE);
  170.         lineEnd = TEScrollGetTELineNumber(end, theTE);
  171.     } else if (start < end) {
  172.         (**theTE).clikStuff = 0xffff;
  173.         lineStart = TEScrollGetTELineNumber(start, theTE);
  174.         (**theTE).clikStuff = 0;
  175.         lineEnd = TEScrollGetTELineNumber(end, theTE);
  176.     } else {
  177.         lineStart = TEScrollGetTELineNumber(start, theTE);
  178.         lineEnd = TEScrollGetTELineNumber(end, theTE);
  179.     }
  180.     (**theTE).clikStuff = savedClikStuff;
  181.     top = (**theTE).destRect.top;
  182.     lineHeight = (**theTE).lineHeight;
  183.     vStart = top + lineStart*lineHeight;
  184.     vEnd = top + (lineEnd+1)*lineHeight;
  185.     viewRect = (**theTE).viewRect;
  186.     tooBig = (vEnd - vStart) > (viewRect.bottom - viewRect.top);
  187.     if (vEnd > viewRect.bottom) {
  188.         if (vStart < viewRect.bottom - lineHeight) return;
  189.         if (tooBig) {
  190.             dv = viewRect.top - vStart;
  191.         } else {
  192.             dv = viewRect.bottom - vEnd;
  193.         }
  194.     } else if (vStart < viewRect.top) {
  195.         if (vEnd > viewRect.top + lineHeight) return;
  196.         if (tooBig) {
  197.             dv = viewRect.bottom - vEnd;
  198.         } else {
  199.             dv = viewRect.top - vStart;
  200.         }
  201.     } else {
  202.         TEScrollAdjustScrollMax(theTE, vScroll);
  203.         return;
  204.     }
  205.     dv = dv/lineHeight;
  206.     oldScrollVal = GetControlValue(vScroll);
  207.     max = GetControlMaximum(vScroll);
  208.     if (oldScrollVal - dv > max) dv = oldScrollVal - max;
  209.     TEScrollScrollText(theTE, vScroll, dv);
  210.     SetControlValue(vScroll, oldScrollVal - dv); 
  211. }
  212.  
  213.  
  214.  
  215. /*----------------------------------------------------------------------------
  216.     TEScrollScrollSelectionIntoView 
  217.     
  218.     Scroll the current selection into view, if necessary.
  219.             
  220.     Entry:    theTE = handle to TextEdit record.
  221.             vScroll = handle to scroll bar control.
  222. ----------------------------------------------------------------------------*/
  223.  
  224. void TEScrollScrollSelectionIntoView (TEHandle theTE, ControlHandle vScroll)
  225. {
  226.     TEScrollScrollRangeIntoView(theTE, (**theTE).selStart, (**theTE).selEnd,
  227.         vScroll);
  228. }
  229.  
  230.  
  231.  
  232. /*----------------------------------------------------------------------------
  233.     TEScrollScrollToMiddle 
  234.     
  235.     Scroll a given point in the text to the middle of the view, if necessary.
  236.             
  237.     Entry:    theTE = handle to TextEdit record.
  238.             offset = offset of character to scroll to middle.
  239.             vScroll = handle to scroll bar control.
  240. ----------------------------------------------------------------------------*/
  241.  
  242. void TEScrollScrollToMiddle (TEHandle theTE, short offset, ControlHandle vScroll)
  243. {
  244.     short lineStart, top, lineHeight, vStart;
  245.     short oldScrollVal, max, dv, viewHeight;
  246.     Rect viewRect;
  247.     short savedClikStuff;
  248.  
  249.     TEScrollAdjustScrollMax(theTE, vScroll);
  250.     savedClikStuff = (**theTE).clikStuff;
  251.     (**theTE).clikStuff = 0xffff;
  252.     lineStart = TEScrollGetTELineNumber(offset, theTE);
  253.     (**theTE).clikStuff = savedClikStuff;
  254.     top = (**theTE).destRect.top;
  255.     lineHeight = (**theTE).lineHeight;
  256.     vStart = top + lineStart*lineHeight;
  257.     viewRect = (**theTE).viewRect;
  258.     if (vStart >= viewRect.top && vStart <= viewRect.bottom - lineHeight) return;
  259.     viewHeight = (viewRect.bottom - viewRect.top) / lineHeight;
  260.     dv = (viewRect.top - vStart)/lineHeight + (viewHeight >> 1);
  261.     oldScrollVal = GetControlValue(vScroll);
  262.     max = GetControlMaximum(vScroll);
  263.     if (oldScrollVal - dv > max) dv = oldScrollVal - max;
  264.     TEScrollScrollText(theTE, vScroll, dv);
  265.     SetControlValue(vScroll, oldScrollVal - dv); 
  266. }
  267.  
  268.  
  269.  
  270. /*----------------------------------------------------------------------------
  271.     TEScrollScrollByPartCode 
  272.     
  273.     Scroll text by part code.
  274.             
  275.     Entry:    theTE = handle to TextEdit record.
  276.             vScroll = handle to scroll bar control.
  277.             part = part code.
  278. ----------------------------------------------------------------------------*/
  279.  
  280. void TEScrollScrollByPartCode (TEHandle theTE, ControlHandle vScroll, short part)
  281. {
  282.     short val, max, page, dv;
  283.  
  284.     page = GetTEPageHeight(theTE);
  285.     val = (**vScroll).contrlValue;
  286.     max = (**vScroll).contrlMax;
  287.     dv = 0;
  288.     switch (part) {
  289.         case inUpButton:
  290.             dv = val > 0 ? 1 : 0;
  291.             break;
  292.         case inDownButton:
  293.             dv = val < max ? -1 : 0;
  294.             break;
  295.         case inPageUp:
  296.             dv = val > page ? page : val;
  297.             break;
  298.         case inPageDown:
  299.             dv = val < max ? -page : 0;
  300.             break;
  301.         case kScrollToHome:
  302.             dv = val;
  303.             break;
  304.         case kScrollToEnd:
  305.             dv = val - max;
  306.             break;
  307.     }
  308.     if (dv != 0) {
  309.         TEScrollScrollText(theTE, vScroll, dv);
  310.         TEScrollAdjustScrollMax(theTE, vScroll);
  311.         SetControlValue(vScroll, val - dv);
  312.     }
  313. }
  314.  
  315.  
  316.  
  317. /*----------------------------------------------------------------------------
  318.     TEScrollAutoScroll 
  319.     
  320.     Handle text autoscrolling.
  321.     
  322.     Entry:    theTE = handle to TextEdit record.
  323.             vScroll = handle to scroll bar control.
  324.             
  325.     Exit:    function result = true
  326. ----------------------------------------------------------------------------*/
  327.  
  328. void TEScrollAutoScroll (TEHandle theTE, ControlHandle vScroll)
  329. {
  330.     Rect viewRect;
  331.     Point where;
  332.     short val, max;
  333.  
  334.     val = GetControlValue(vScroll);
  335.     max = GetControlMaximum(vScroll);
  336.     viewRect = (**theTE).viewRect;
  337.     GetMouse(&where);
  338.     ClipRect(&qd.thePort->portRect);
  339.     if (where.v < viewRect.top && val > 0) {
  340.         TEScrollScrollText(theTE, vScroll, 1);
  341.         SetControlValue(vScroll, val-1);
  342.     } else if (where.v > viewRect.bottom && val < max) {
  343.         TEScrollScrollText(theTE, vScroll, -1);
  344.         SetControlValue(vScroll, val+1);
  345.     }
  346.     ClipRect(&viewRect);
  347. }
  348.